package com.cl.auth.cas;

import java.io.IOException;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.cas.CasToken;
import org.apache.shiro.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.cl.auth.AuthException;
import com.cl.dao.SearchDao;
import com.cl.entity.UUser;

/**
 * 故宫定制版CAS REALM
 * 故宫CAS在官方的基础上做过变动，所以相应的CAS REALM我们也要做相应的变动
 * @author Administrator
 *
 */
public class GCasRealm extends CasRealm {

	protected Logger log = LoggerFactory.getLogger(this.getClass());

	@Value("#{applicationProperties['shiro.casValicationURL']}")
	protected String casValicationURL;
	
	@Value("#{applicationProperties['shiro.casRecallURL']}")
	protected String casRecallURL;
	
	@Autowired
	private SearchDao<?> searchDao;
	
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        CasToken casToken = (CasToken) token;
        if (token == null) {
			throw new AuthException("密码认证失败!");
        }        
        String ticket = (String)casToken.getCredentials();
        if (!StringUtils.hasText(ticket)) {
			throw new AuthException("密码认证失败!");
        }
		try {
			String userDn = getUserDn(ticket);
	        UUser user = searchDao.getUserByDn(userDn);
	        return new SimpleAuthenticationInfo(user, ticket, getName());
		} catch (Exception e) {
			throw new AuthException("密码认证失败!");
		}
    }

    private String getUserDn(String ticket) throws IOException {
		String url = casValicationURL + "?service=" + casRecallURL + "&ticket=" + ticket + "&default_cmd=";
		String s = getCasResponse(url, "GBK");
		int i0, i1, i2;
		i0 = s.indexOf("<cas_authenticationSuccess>");
		i1 = s.indexOf("<cas_user>");
		i2 = s.indexOf("</cas_user>");
		String userDn = "";
		if ((i0 >= 0) && (i1 >= 0) && (i2 >= 0))
			userDn = s.substring(i1 + 10, i2);
		return userDn;
	}

	private String getCasResponse(String url, String code) throws IOException {
		HttpClientParams params = new HttpClientParams();
		params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(0, true));
		HttpClient httpclient = new HttpClient(new MultiThreadedHttpConnectionManager());
		httpclient.setParams(params);
		GetMethod getMethod = new GetMethod(url);
		httpclient.executeMethod(getMethod);
		byte[] rByte = getMethod.getResponseBody();
		String rStr = new String(rByte, code);
		getMethod.releaseConnection();
		return rStr;
	}
	
}
